﻿<Serializable()>
Public Class Project
    Implements ICloneable

    Private NameValue As String = "Nuova applicazione"
    Private pYearsBackOffset As Integer = 0
    Private NumberOfYearsValue As Integer = 3
    Private ZoomFactorValue As Single = 1
    Private pProjectSOPDate As Date = Now
    Private pProjectDAPDate As Date = Now
    Private pProjectHighlights As String = ""
    Private pProjectRisk As Integer = ProjectConstantValues.ProjectStatusValues.L3DStatusYellow
    Private L3OwnerValue As String
    Private ApplicationOwnerValue As String
    Private ModelValue As String
    Private VisibleMilestonesValue As VisibleMilestonesStructure
    Private WithEvents pProjectElements As New VMGenLibrary.VMObjects.PowerCollection(Of L3DObjectsLibrary.ProjectElement)
    Public Event QueryChange(ByVal sender As Object, ByVal e As QueryChangeEventArgs)
    Public Event PropertyChange(ByVal sender As L3DObjectsLibrary.Project)

#Region "PROPERTIES DEFINITION"
    Public Property L3Owner As String
        Get
            Return L3OwnerValue
        End Get
        Set(ByVal value As String)
            L3OwnerValue = value
        End Set
    End Property
    Public Property ApplicationOwner As String
        Get
            Return ApplicationOwnervalue
        End Get
        Set(ByVal value As String)
            ApplicationOwnervalue = value
        End Set
    End Property
    Public Property Model As String
        Get
            Return ModelValue
        End Get
        Set(ByVal value As String)
            ModelValue = value
        End Set
    End Property
    Public Property Name As String
        Get
            Return NameValue
        End Get
        Set(ByVal value As String)
            NameValue = value
            RaiseEvent PropertyChange(Me)
        End Set
    End Property
    Public ReadOnly Property ProjectStartDate As Date
        Get
            Dim StartDate As Date
            Dim FirstDate As Date
            For Each Element As L3DObjectsLibrary.ProjectElement In ProjectElements
                FirstDate = VMGenLibrary.DateTimeOperations.FirstDate(Element.ElementStartDate, Element.ElementRealStartDate)
                If StartDate > FirstDate Or Element Is ProjectElements.First Then
                    StartDate = FirstDate
                End If
            Next
            If DateTime.Compare(StartDate, Now) < 1 And ProjectElements.Count = 0 Then
                StartDate = Now
            End If
            Return StartDate
        End Get
    End Property
    Public ReadOnly Property ProjectEndDate As Date
        Get
            Dim EndDate As Date
            Dim LastDate As Date
            For Each Element As L3DObjectsLibrary.ProjectElement In ProjectElements
                LastDate = VMGenLibrary.DateTimeOperations.LastDate(Element.ElementEndDate, Element.ElementRealEndDate)
                If EndDate < LastDate Or Element Is ProjectElements.First Then
                    EndDate = LastDate
                End If
            Next
            If DateTime.Compare(EndDate, Now) < 1 And ProjectElements.Count = 0 Then
                EndDate = Now
            End If
            Return EndDate
        End Get
    End Property
    Public Property ProjectSOPDate As Date
        Get
            Return pProjectSOPDate
        End Get
        Set(ByVal value As Date)
            Dim SOP As L3DObjectsLibrary.Milestone = GetSpecialMilestone(L3DObjectsLibrary.Milestone.SpecialIDValues.SOP)
            pProjectSOPDate = value
            With SOP
                .MilestoneDate = value
                .MilestoneRealDate = value
            End With
        End Set
    End Property
    Public Property ProjectDAPDate As Date
        Get
            Return pProjectDAPDate
        End Get
        Set(ByVal value As Date)
            Dim DAP As L3DObjectsLibrary.Milestone = GetSpecialMilestone(L3DObjectsLibrary.Milestone.SpecialIDValues.DAP)
            pProjectDAPDate = value
            With DAP
                .MilestoneDate = value
                .MilestoneRealDate = value
            End With
        End Set
    End Property
    Public ReadOnly Property FirstProjectYear(Optional ByVal Offset As Integer = 0) As Integer
        Get
            Return Val(Format(ProjectStartDate, "yyyy")) - Offset
        End Get
    End Property
    Public Property ProjectHighlights
        Get
            Return pProjectHighlights
        End Get
        Set(ByVal value)
            pProjectHighlights = value
        End Set
    End Property
    Public Property ProjectRisk As Integer
        Get
            Return pProjectRisk
        End Get
        Set(ByVal value As Integer)
            pProjectRisk = value
        End Set
    End Property
    Public Property ProjectElements As VMGenLibrary.VMObjects.PowerCollection(Of L3DObjectsLibrary.ProjectElement)
        Get
            Return pProjectElements
        End Get
        Set(ByVal value As PowerCollection(Of L3DObjectsLibrary.ProjectElement))
            pProjectElements.Dispose()
            pProjectElements = value
        End Set
    End Property
    Public ReadOnly Property AllCarsKm(Optional ByVal EOBDOnly As Boolean = False, Optional ByVal EOBDExclude As Boolean = False) As Integer
        Get
            Dim km As Integer
            Dim Fasi = From el As L3DObjectsLibrary.ProjectElement In Me.ProjectElements
                       Select el
                       Where el.ElementType = ElementTypeValue.L3DPhase
            For Each Fase As L3DObjectsLibrary.ProjectElement In Fasi
                For Each Gruppo As L3DObjectsLibrary.Group In Fase.Groups
                    km = km + Gruppo.AllCarsKm(EOBDOnly, EOBDExclude)
                Next
            Next
            Return km
        End Get
    End Property
    Public ReadOnly Property AllCars(Optional ByVal EOBDOnly As Boolean = False, Optional ByVal EOBDExclude As Boolean = False) As Collection
        Get
            Dim Cars As New Collection
            Dim Fasi = From el As ProjectElement In Me.ProjectElements
                      Select el
                      Where el.ElementType = ElementTypeValue.L3DPhase
            For Each Fase As L3DObjectsLibrary.ProjectElement In Fasi
                For Each Car As L3DObjectsLibrary.Car In Fase.AllCars(EOBDOnly, EOBDExclude)
                    Cars.Add(Car)
                Next
            Next
            Return Cars
        End Get
    End Property
    Public Property VisibleMilestones As VisibleMilestonesStructure
        Get
            Return VisibleMilestonesValue
        End Get
        Set(ByVal value As VisibleMilestonesStructure)
            VisibleMilestonesValue = value
            Dim Dap As Milestone = GetSpecialMilestone(SpecialIDValues.DAP)
            Dim Sop As Milestone = GetSpecialMilestone(SpecialIDValues.SOP)
            Dap.ShowInPlan = value.DAP
            Sop.ShowInPlan = value.SOP
        End Set
    End Property
#End Region
#Region "METHODS"
    Public Sub New()
        Dim DAP As L3DObjectsLibrary.Milestone = InsertSpecialMilestone(L3DObjectsLibrary.Milestone.SpecialIDValues.DAP)
        Dim SOP As L3DObjectsLibrary.Milestone = InsertSpecialMilestone(L3DObjectsLibrary.Milestone.SpecialIDValues.SOP)
        With DAP
            .MilestoneDate = ProjectDAPDate
            .MilestoneRealDate = ProjectDAPDate
            .ShowInPlan = VisibleMilestones.DAP
        End With
        With SOP
            .MilestoneDate = ProjectSOPDate
            .MilestoneRealDate = ProjectSOPDate
            .ShowInPlan = VisibleMilestones.SOP
        End With
    End Sub
    Public Sub OnQueryChange()
        RaiseEvent QueryChange(Me, New QueryChangeEventArgs)
    End Sub
    Public Function GetGroupFromCar(ByVal Car As L3DObjectsLibrary.Car) As L3DObjectsLibrary.Group
        Dim Result As L3DObjectsLibrary.Group = Nothing
        For Each Element As L3DObjectsLibrary.ProjectElement In ProjectElements
            For Each Group As L3DObjectsLibrary.Group In Element.Groups
                For Each CarInGroup As L3DObjectsLibrary.Car In Group.Cars
                    If Group.Cars.Contains(Car) Then
                        Result = Group
                    End If
                Next
            Next
        Next
        Return Result
    End Function
    Public Function GetElementFromGroup(ByVal Group As L3DObjectsLibrary.Group) As L3DObjectsLibrary.ProjectElement
        Dim Result As L3DObjectsLibrary.ProjectElement = Nothing
        For Each Element As L3DObjectsLibrary.ProjectElement In ProjectElements
            If Element.Groups.Contains(Group) Then
                Result = Element
                Exit For
            End If
        Next
        Return Result
    End Function
    Public Function GetSpecialDate(Optional ByVal Name As String = "sop", Optional ByVal Replan As Boolean = False) As Date
        Dim Data As Date = #1/1/2010#
        Dim Elementi = From el As L3DObjectsLibrary.ProjectElement In Me.ProjectElements
                         Select el
                         Where el.ElementType = ElementTypeValue.L3DMilestone Or el.ElementType = ElementTypeValue.L3DMixed
        Dim MilestoneName As String
        For Each Elemento As L3DObjectsLibrary.ProjectElement In Elementi
            For Each Milestone As L3DObjectsLibrary.Milestone In Elemento.Milestones
                MilestoneName = Trim(LCase(Milestone.Name))
                If MilestoneName = "sop" Or MilestoneName = "vsop" Or MilestoneName = "job1" Or MilestoneName = "vsorp" Or MilestoneName = "sorp" Then
                    MilestoneName = "sop"
                End If
                If LCase(Name) = LCase(MilestoneName) Then
                    If Replan = True Then
                        Data = Milestone.MilestoneRealDate
                    Else
                        Data = Milestone.MilestoneDate
                    End If
                End If
            Next
        Next
        If LCase(Name) = "sop" And Data = #1/1/2010# Then
            Data = ProjectEndDate
        End If
        If LCase(Name) = "dap" And Data = #1/1/2010# Then
            Data = DateAdd(DateInterval.Day, -7, GetSpecialDate("sop"))
        End If
        Return Data
    End Function
    Public Function GetSpecialMilestone(ByVal IDValue As Integer) As L3DObjectsLibrary.Milestone
        Dim Milestone As L3DObjectsLibrary.Milestone = Nothing
        For Each El As L3DObjectsLibrary.ProjectElement In ProjectElements
            For Each Ms As L3DObjectsLibrary.Milestone In El.Milestones
                If Ms.SpecialID = IDValue Then
                    Milestone = Ms
                End If
            Next
        Next
        Return Milestone
    End Function
    Public Function MileageForecast(ByVal CurrentStatusDate As Date, ByVal ForecastStatusDate As Date, Optional ByVal EOBDOnly As Boolean = False, Optional ByVal EOBDExclude As Boolean = False) As Integer
        Dim KmForecast As Integer
        For Each Elemento As L3DObjectsLibrary.ProjectElement In Me.ProjectElements
            If Elemento.ElementType = ElementTypeValue.L3DPhase Then
                KmForecast = KmForecast + Elemento.MileageForecast(CurrentStatusDate, ForecastStatusDate, EOBDOnly, EOBDExclude)
            End If
        Next
        Return KmForecast
    End Function
    Public Function InsertSpecialMilestone(ByVal MilestoneSpecialID As Integer) As L3DObjectsLibrary.Milestone
        Dim Milestone As New L3DObjectsLibrary.Milestone
        Dim El As New L3DObjectsLibrary.ProjectElement
        With Milestone
            .SpecialID = MilestoneSpecialID
        End With
        El.Milestones.Add(Milestone)
        ProjectElements.Add(El)
        Return Milestone
    End Function
    Public Function Clone() As Object Implements System.ICloneable.Clone
        Dim ClProj As Project = CType(ObjManagement.CloneObject(Me), Project)
        For Each El As ProjectElement In ClProj.ProjectElements
            ClProj.AddRemoveElementHandler(El, AddRemove.Add)
        Next
        Return ClProj
    End Function
    Private Sub AddRemoveElementHandler(ByVal El As ProjectElement, ByVal Action As AddRemove)
        With El
            Select Case Action
                Case AddRemove.Add
                    AddHandler .NowEmpty, AddressOf ProjectElement_NowEmpty
                    AddHandler .QueryChange, AddressOf ProjectElement_QueryChange
                Case AddRemove.Remove
                    RemoveHandler .NowEmpty, AddressOf ProjectElement_NowEmpty
                    RemoveHandler .QueryChange, AddressOf ProjectElement_QueryChange
            End Select
        End With
    End Sub
#End Region

#Region "EVENTS MANAGEMENT"

    Private Sub Project_ElementCountChanging(ByVal sender As Object, ByVal e As VMGenLibrary.Structures.PowercollectionEventArgs) Handles pProjectElements.CountChanging, pProjectElements.ItemsExchanging, pProjectElements.ItemsMoving
        RaiseEvent QueryChange(Me, New QueryChangeEventArgs)
    End Sub
    Private Sub Project_ElementCountChange(ByVal sender As Object, ByVal e As VMGenLibrary.Structures.PowercollectionEventArgs) Handles pProjectElements.CountChanged
        Dim Element As L3DObjectsLibrary.ProjectElement = e.ObjectMoved
        With Element
            If e.Action = CountChangedAction.Added Then
                AddRemoveElementHandler(Element, AddRemove.Add)
            ElseIf e.Action = CountChangedAction.Removed Then
                AddRemoveElementHandler(Element, AddRemove.Remove)
            End If
        End With
    End Sub
    Private Sub ProjectElement_NowEmpty(ByVal sender As L3DObjectsLibrary.ProjectElement)
        Dim Index = ProjectElements.IndexOf(sender)
        If Index > -1 Then
            ProjectElements.RemoveAt(Index)
        End If
    End Sub
    Private Sub ProjectElement_QueryChange(ByVal sender As Object, ByVal e As QueryChangeEventArgs)
        RaiseEvent QueryChange(Me, e)
    End Sub
#End Region

End Class
